package com.unlcn.ils.wms.web.controller.annotation;

import cn.huiyunche.commons.domain.ResultDTO;
import com.unlcn.ils.wms.backend.bo.logBO.OperatorLogBO;
import com.unlcn.ils.wms.backend.service.operatorLog.OperatorLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by DELL on 2017/9/12.
 */
@Aspect
public class OperatorLogAspect {
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private long BEGIN_TIME ;//获取开始时间


    private long END_TIME;//获取结束时间


    private OperatorLogBO operatorLogBO = new OperatorLogBO();

    @Autowired
    private OperatorLogService operatorLogService;

    @Pointcut("execution(* com.unlcn.ils.wms.web.controller..*.*(..))")
    private void controllerAspect(){}

    /**
     * 方法开始执行
     */
    @Before("controllerAspect()")
    public void doBefore(){
        BEGIN_TIME = new Date().getTime();
    }

    /**
     * 方法结束执行
     */
    @After("controllerAspect()")
    public void after(){
        END_TIME = new Date().getTime();
    }

    /**
     * 方法结束执行后的操作
     */
    @AfterReturning("controllerAspect()")
    public void doAfter(){
        if("10".equals(operatorLogBO.getOpStatus())){
            operatorLogBO.setOpTime(sdf.format(new Date(BEGIN_TIME)));
        }
        System.out.println("例外通知-----------------------------------");
    }

    /**
     * 方法有异常时的操作
     */
    @AfterThrowing("controllerAspect()")
    public void doAfterThrow(){
        System.out.println("例外通知-----------------------------------");
    }

    /**
     * 方法执行
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("controllerAspect()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        //日志实体对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //获取当前登陆用户信息
        //User loginUser = SessionUtil.getLoginSession(request);
        /*if(loginUser==null){
            log.setOpUserId("—— ——");
        }else{*/
            operatorLogBO.setOpUserName("zhangsan");//(loginUser.getUserAuth().getIdentity());
        /*}*/

        /**
         * 获取实现类
         */
        Object target = pjp.getTarget();// 拦截的实体类，就是当前正在执行的controller
        String methodName = pjp.getSignature().getName();// 拦截的方法名称。当前正在执行的方法
        Object[] args = pjp.getArgs();// 拦截的方法参数
        Signature sig = pjp.getSignature();// 拦截的放参数类型
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();
        ResultDTO object = null;
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
            //method = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        } catch (NoSuchMethodException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (SecurityException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if (null != method) {
            if (method.isAnnotationPresent(LogAnnotation.class)) {// 判断是否包含自定义的注解LogAnnotation
                LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
                operatorLogBO.setOpModules(logAnnotation.modules());
                operatorLogBO.setOpMethods(logAnnotation.methods());
                operatorLogBO.setOpIp(getIp(request));
                operatorLogBO.setOpRequestUrl(request.getRequestURI());

                try {
                    object = (ResultDTO)pjp.proceed();
                    if(object.isSuccess()){
                        operatorLogBO.setOpDescription("执行成功");
                        operatorLogBO.setOpStatus("10");

                    }else{
                        operatorLogBO.setOpDescription("执行失败");
                        operatorLogBO.setOpStatus("20");
                    }
                    operatorLogBO.setOpTime(sdf.format(new Date()));
                    operatorLogService.insert(operatorLogBO);
                } catch (Throwable e) {
                    // TODO Auto-generated catch block
                    operatorLogBO.setOpDescription("执行失败");
                    operatorLogBO.setOpStatus("20");
                }
            } else {//没有包含注解
                object = (ResultDTO) pjp.proceed();
                operatorLogBO.setOpDescription("此操作不包含注解");
                operatorLogBO.setOpStatus("30");
            }
        } else { //不需要拦截直接执行
            object = (ResultDTO) pjp.proceed();
            operatorLogBO.setOpDescription("不需要拦截直接执行");
            operatorLogBO.setOpStatus("40");
        }
        return object;
    }

    /**
     * 获取ip地址
     * @param request
     * @return
     */
    private String getIp(HttpServletRequest request){
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }
}
